iT邦幫忙

0

WebSocket 延遲幾乎由「伺服器放哪裡」決定:從台北看亞洲各區的物理下限與實測腳本

  • 分享至 

  • xImage
  •  

本文改寫自 Hibira 部落格的文章,以台灣使用者的角度重新整理。本文由 Pusher 相容 WebSocket 服務 Hibira 的開發團隊撰寫。

聊天訊息、報價跳動、「對方正在輸入…」,只要在大約 0.1 秒內送達,使用者就會覺得是即時的。這個時間預算大部分花在網路上,而網路時間大部分由一件事決定:WebSocket 伺服器放在哪裡。

很多國外 SaaS 預設把即時服務放在美國東部。如果沒特別注意,兩個在台北的使用者互傳一則訊息,事件可能要橫越太平洋兩次。這篇文章先算出物理下限,再給一支腳本讓你從自己使用者所在的網路實測。

光速決定了下限

光在光纖裡每毫秒大約走 200 公里,約是真空光速的三分之二。所以和 1,000 公里外的伺服器來回一趟,就算不計路由、排隊和處理,至少也要 10 ms。實際的海纜不會走大圓航線、路由器也會增加延遲,實測值常是下限的 2 到 4 倍(香港到台北下限約 8 ms,我們實測約 30 ms)。

從台北到各主要雲端區域的下限:

從台北到 大圓距離 最短來回時間
香港 約 810 km 約 8 ms
首爾 約 1,490 km 約 15 ms
東京 約 2,100 km 約 21 ms
新加坡 約 3,250 km 約 32 ms
美國西部(奧勒岡) 約 10,000 km 約 100 ms
美國東部(維吉尼亞) 約 12,600 km 約 126 ms

這是物理極限、不是 benchmark:任何網路都不可能比它快,實際只會更慢。Pusher 的預設叢集 mt1 也在美國東部(Pusher 也有亞洲叢集,正在用的人可以確認一下自己的 app 建在哪個叢集)。

為什麼即時功能比網頁更怕延遲

網頁載入時只來回幾次;即時功能則是每一次互動都要付一次來回。

  • 輸入中提示、游標同步:每秒送好幾次 client event,來回一慢就跟不上手。
  • 聊天:從發送者到你的後端、到 WebSocket 服務、再到所有人,每一段都會加上距離。
  • Presence(誰在線上):更新慢的話,已經離開的人還會掛在線上名單。
  • 重新連線:手機在 Wi-Fi 和 4G 之間切換時,TLS 握手加上重新訂閱,會連續來回好幾次。

把每一段都算進去

後端推送一個事件時,事件會經過三段:

  1. 使用者操作 → 你的後端
  2. 你的後端 → WebSocket 服務的 HTTP API
  3. WebSocket 服務 → 所有訂閱的用戶端

第 1、3 段取決於使用者在哪,第 2 段取決於後端在哪。原則是:WebSocket 伺服器放在使用者附近,可以的話後端也放在它附近。

自己量

表格只是起點。Pusher 協定有 pusher:ping,伺服器會立刻回 pusher:pong,不用推送任何事件就能量來回時間。存成 ping.mjs,用 Node.js 22 以上(內建 WebSocket)執行:

// node ping.mjs YOUR_APP_KEY [host]
const [key, host = 'ws.hibira.io'] = process.argv.slice(2);
const ws = new WebSocket(`wss://${host}/app/${key}?protocol=7&client=js&version=8.4.0`);
const times = [];
let sent = 0;

const ping = () => {
  sent = performance.now();
  ws.send(JSON.stringify({ event: 'pusher:ping', data: {} }));
};

ws.onmessage = (msg) => {
  const { event } = JSON.parse(msg.data);
  if (event === 'pusher:pong') times.push(performance.now() - sent);
  if (event !== 'pusher:connection_established' && event !== 'pusher:pong') return;
  if (times.length < 20) return void setTimeout(ping, 250);
  times.sort((a, b) => a - b);
  console.log(`best ${times[0].toFixed(1)} ms, median ${((times[9] + times[10]) / 2).toFixed(1)} ms`);
  ws.close();
};

要注意的是,這支腳本量的是已經建立好的 WebSocket 來回時間,不包含推送到訂閱者的時間,也不包含建立連線的時間。建議從幾種代表性的網路(包括行動網路)多量幾次,看中位數和 p95。

只要換掉 host,任何 Pusher 相容的伺服器都能用同一支腳本比較,包括自架的 Laravel Reverb 或 Soketi。

  • 比較 中位數;最小值可以看出路由離下限有多近。
  • 從使用者所在的地方量:各國的雲端主機、家用網路的筆電,還有 手機熱點(行動網路會再多一層延遲)。
  • 想看真實使用者的數字,可以記錄 pusher-js 從 connecting 到 connected 的時間,連同國家一起送進分析工具。

關於 Hibira

Hibira 是我們團隊開發、營運的 Pusher Channels 相容 WebSocket 服務,Laravel Echo、pusher-js 和各語言官方的 pusher 伺服器套件都能直接用,只要換 host。目前跑在香港(AWS ap-east-1),從台北的物理下限約 8 ms;接下來準備東京區,再來是新加坡。上面這張距離表,就是我們決定區域順序時用的算法。

Free 方案長期免費、不用綁卡:同時連線 100、每日 20 萬則訊息、1 個 app、同時 200 個頻道、單則 4 KB、每月 200 萬次送達、2,000 個推播訂閱(只計算推送的訊息)。付費方案以美元計價,月付 Hobby $19、Starter $39、Pro $89、Advanced $169、Business $279、Scale $699。

歡迎在留言分享你從自己網路量到的數字,或是遇到的問題,我們團隊都會看。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言